
#ifndef DRIVER_PIC_H
#define DRIVER_PIC_H

#include <lib/type.h>
#include <arch/interrupt.h>
#include <os/exception.h>


//PIC master and slave chip
#define PIC_MASTER 0x00
#define PIC_SLAVE 0x01

//define command and data port
#define PIC_MASTER_CMD 0x20
#define PIC_MASTER_STATUS 0x20
#define PIC_MASTER_DATA 0x21
#define PIC_MASTER_MASK 0x21

#define PIC_SLAVE_CMD 0xA0
#define PIC_SLAVE_STATUS 0xA0
#define PIC_SLAVE_DATA 0xA1
#define PIC_SLAVE_MASK 0xA1

//define PIC support irq max num
#define PIC_INTMAX 0x08

//define every PIC chips vector offset
#define PIC_MASTER_VECOFF 0x08
#define PIC_SLAVE_VECOFF 0x70

//define ICW1 mask
//if set,need send ICW4 cmd
#define PIC_ICW1_ICW4 0x01
//if set,we used single chips,or use cascaded
#define PIC_ICW1_SNGL 0x02
//if need used aligned
#define PIC_ICW1_ADI 0x04
//if set,use level triggered,or use edge triggered mode
#define PIC_ICW1_LTIM 0x08
//init
#define PIC_ICW1_INIT 0x10
//unused bits
#define PIC_ICW1_MASK 0x1f

//define ICW2 mask
#define PIC_ICW2_VEC 0xf8

//define ICW3 mask
#define PIC_ICW3_SCASCADED 0xf8

//define ICW4
#define PIC_ICW4_8086 0x01
#define PIC_ICW4_AEOI 0x02
#define PIC_ICW4_MBUF 0x04
#define PIC_ICW4_BUF 0x08
#define PIC_ICW4_SFNM 0x10

//define OCW2
//indiatify irq
#define PIC_OCW2_INIRQ 0x07
//eof
#define PIC_OCW2_EOF 0x20
//select specific object
#define PIC_OCW2_SLET 0x40
//rotation opinion
#define PIC_OCW2_ROTATION 0x80
//eof specific interrupt
#define PIC_OCW2_SPEEOF PIC_OCW2_EOF | PIC_OCW2_SLET
//specific proior
#define PIC_OCW2_SPEPROIOR PIC_OCW2_SLET
//rotation specific proior
#define PIC_OCW2_ROTSPEPROIOR PIC_OCW2_ROTATION | PIC_OCW2_SPEPROIOR
//rotation fixed proior
#define PIC_OCW2_ROTFIXPROIOR PIC_OCW2_ROTATION

//define OCW3
#define PIC_OCW3_ESMM 0x40
#define PIC_OCW3_SMM 0x20
#define PIC_OCW3_SIGN 0x08
#define PIC_OCW3_REFER 0x04
#define PIC_OCW3_RR 0x02
#define PIC_OCW3_RIS 0x01
//set specific mask
#define PIC_OCW3_SETSPEMASK PIC_OCW3_ESMM | PIC_OCW3_SMM | PIC_OCW3_SIGN
//read IRR
#define PIC_OCW3_RIRR PIC_OCW3_RR | PIC_OCW3_SIGN
//read ISR
#define PIC_OCW3_RISR  PIC_OCW3_RIS | PIC_OCW3_SIGN

//irq EOI cmd
#define PIC_EOI 0x20

//PIC status register
//PIC read IRR cmd
#define PIC_READ_IRR 0x0A
//PIC read ISR cmd
#define PIC_READ_ISR 0x0B

//function
void PicInit();                                   //pic chip initiliaztion
int PitSendCMD(uint8_t chips, uint8_t cmd);      //send cmd to chips
int PicSendData(uint8_t chips, uint8_t data);    //send data to chips
int PicReadCMD(uint8_t chips, uint8_t *cmd);     //read cmd
int PicReadData(uint8_t chips, uint8_t *data);   //read data

void PicSetINTMask(uint8_t irq);       //mask irq
void PicClearINTMask(uint8_t irq); //clear mask irq

void PicSendEOI(uint8_t irq);                          //send EOI cmd to end of interrupt
void PicDisable();                                     //if use APIC　or IOAPIC,we need disable PIC
uint16_t PicReadISR();                                 //read ISR register status
uint16_t PicReadIRR();                                 //read IRR register status
#endif